﻿#include "MirConnection.h"
#include "../Settings.h"
#include "../../Shared/ServerPackets.h"
#include "../../Shared/Enums.h"
#include "../MirDatabase/CharacterInfo.h"
#include "../../Shared/Functions/Functions.h"
#include "../../Shared/Globals.h"
#include "../MirDatabase/MagicInfo.h"
#include "../../Shared/Language.h"
#include "../../Shared/Data/Stat.h"
#include "../../Shared/Data/IntelligentCreatureData.h"

using namespace Server::MirDatabase;
using namespace Server::MirEnvir;
using namespace Server::MirObjects;
namespace C = ClientPackets;
namespace S = ServerPackets;

namespace Server::MirNetwork
{

    Server::MirEnvir::Envir *MirConnection::getEnvir()
    {
        return Envir::getMain();
    }

    Server::MessageQueue *MirConnection::getMessageQueue()
    {
        return MessageQueue::getInstance();
    }

    bool MirConnection::getDisconnecting() const
    {
        return _disconnecting;
    }

    void MirConnection::setDisconnecting(bool value)
    {
        if (_disconnecting == value)
        {
            return;
        }
        _disconnecting = value;
        TimeOutTime = getEnvir()->getTime() + 500;
    }

//C# TO C++ CONVERTER TODO TASK: There is no C++ equivalent to 'ToString':
    MirConnection::MirConnection(int sessionID, TcpClient *client) : SessionID(sessionID), IPAddress(client->Client->RemoteEndPoint->ToString().Split(':')[0]), TimeConnected(getEnvir()->getTime())
    {

        int connCount = 0;
        for (int i = 0; i < getEnvir()->Connections.size(); i++)
        {
            MirConnection *conn = getEnvir()->Connections[i];
            if (conn->IPAddress == IPAddress && conn->Connected)
            {
                connCount++;

                if (connCount >= Settings::MaxIP)
                {
                    getMessageQueue()->EnqueueDebugging(IPAddress + ", Maximum connections reached.");
                    conn->SendDisconnect(5);
                }
            }
        }

        getMessageQueue()->Enqueue(IPAddress + ", Connected.");

        _client = client;
        _client->NoDelay = true;

        TimeOutTime = TimeConnected + Settings::TimeOut;


        _receiveList = new ConcurrentQueue<Packet*>();
        _sendList = new ConcurrentQueue<Packet*>();
        S::Connected tempVar();
        _sendList->Enqueue(&tempVar);
        _retryList = std::deque<Packet*>();

        Connected = true;
        BeginReceive();
    }

    void MirConnection::BeginReceive()
    {
        if (!Connected)
        {
            return;
        }

        try
        {
            _client->Client->BeginReceive(_rawBytes, 0, _rawBytes.size(), SocketFlags::None, [&] (System::IAsyncResult ar) {ReceiveData(ar);}, _rawBytes);
        }
        catch (...)
        {
            setDisconnecting(true);
        }
    }

    void MirConnection::ReceiveData(IAsyncResult *result)
    {
        if (!Connected)
        {
            return;
        }

        int dataRead;

        try
        {
            dataRead = _client->Client->EndReceive(result);
        }
        catch (...)
        {
            setDisconnecting(true);
            return;
        }

        if (dataRead == 0)
        {
            setDisconnecting(true);
            return;
        }

        std::vector<unsigned char> rawBytes = dynamic_cast<std::vector<unsigned char>>(result->AsyncState);

        std::vector<unsigned char> temp = _rawData;
        _rawData = std::vector<unsigned char>(dataRead + temp.size());
        Buffer::BlockCopy(temp, 0, _rawData, 0, temp.size());
        Buffer::BlockCopy(rawBytes, 0, _rawData, temp.size(), dataRead);

        Packet *p;
        while ((p = Packet::ReceivePacket(_rawData, _rawData)) != nullptr)
        {
            _receiveList->Enqueue(p);
        }

        BeginReceive();
    }

    void MirConnection::BeginSend(std::vector<unsigned char> &data)
    {
        if (!Connected || data.empty())
        {
            return;
        }

        //Interlocked.Add(ref Network.Sent, data.Count);

        try
        {
            _client->Client->BeginSend(data.ToArray(), 0, data.size(), SocketFlags::None, [&] (System::IAsyncResult ar) {SendData(ar);}, getDisconnecting());
        }
        catch (...)
        {
            setDisconnecting(true);
        }
    }

    void MirConnection::SendData(IAsyncResult *result)
    {
        try
        {
            _client->Client->EndSend(result);
        }
        catch (...)
        {
        }
    }

    void MirConnection::Enqueue(Packet *p)
    {
        if (_sendList != nullptr && p != nullptr)
        {
            _sendList->Enqueue(p);
        }
    }

    void MirConnection::Process()
    {
        if (_client == nullptr || !_client->Connected)
        {
            Disconnect(20);
            return;
        }

        while (!_receiveList->IsEmpty && !getDisconnecting())
        {
            Packet *p;
            if (!_receiveList->TryDequeue(p))
            {
                continue;
            }
            TimeOutTime = getEnvir()->getTime() + Settings::TimeOut;
            ProcessPacket(p);

            if (_receiveList == nullptr)
            {
                return;
            }
        }

        while (_retryList.size() > 0)
        {
            _receiveList->Enqueue(_retryList.pop_front());
        }

        if (getEnvir()->getTime() > TimeOutTime)
        {
            Disconnect(21);
            return;
        }

        if (_sendList == nullptr || _sendList->Count <= 0)
        {
            return;
        }

        std::vector<unsigned char> data;
        while (!_sendList->IsEmpty)
        {
            Packet *p;
            if (!_sendList->TryDequeue(p) || p == nullptr)
            {
                continue;
            }
            data.AddRange(p->GetPacketBytes());
        }

        BeginSend(data);
    }

    void MirConnection::ProcessPacket(Packet *p)
    {
        if (p == nullptr || getDisconnecting())
        {
            return;
        }

        switch (p->getIndex())
        {
            case static_cast<short>(ClientPacketIds::ClientVersion):
                ClientVersion(static_cast<C::ClientVersion*>(p));
                break;
            case static_cast<short>(ClientPacketIds::Disconnect):
                Disconnect(22);
                break;
            case static_cast<short>(ClientPacketIds::KeepAlive): // Keep Alive
                ClientKeepAlive(static_cast<C::KeepAlive*>(p));
                break;
            case static_cast<short>(ClientPacketIds::NewAccount):
                NewAccount(static_cast<C::NewAccount*>(p));
                break;
            case static_cast<short>(ClientPacketIds::ChangePassword):
                ChangePassword(static_cast<C::ChangePassword*>(p));
                break;
            case static_cast<short>(ClientPacketIds::Login):
                Login(static_cast<C::Login*>(p));
                break;
            case static_cast<short>(ClientPacketIds::NewCharacter):
                NewCharacter(static_cast<C::NewCharacter*>(p));
                break;
            case static_cast<short>(ClientPacketIds::DeleteCharacter):
                DeleteCharacter(static_cast<C::DeleteCharacter*>(p));
                break;
            case static_cast<short>(ClientPacketIds::StartGame):
                StartGame(static_cast<C::StartGame*>(p));
                break;
            case static_cast<short>(ClientPacketIds::LogOut):
                LogOut();
                break;
            case static_cast<short>(ClientPacketIds::Turn):
                Turn(static_cast<C::Turn*>(p));
                break;
            case static_cast<short>(ClientPacketIds::Walk):
                Walk(static_cast<C::Walk*>(p));
                break;
            case static_cast<short>(ClientPacketIds::Run):
                Run(static_cast<C::Run*>(p));
                break;
            case static_cast<short>(ClientPacketIds::Chat):
                Chat(static_cast<C::Chat*>(p));
                break;
            case static_cast<short>(ClientPacketIds::MoveItem):
                MoveItem(static_cast<C::MoveItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::StoreItem):
                StoreItem(static_cast<C::StoreItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::DepositRefineItem):
                DepositRefineItem(static_cast<C::DepositRefineItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::RetrieveRefineItem):
                RetrieveRefineItem(static_cast<C::RetrieveRefineItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::RefineCancel):
                RefineCancel(static_cast<C::RefineCancel*>(p));
                break;
            case static_cast<short>(ClientPacketIds::RefineItem):
                RefineItem(static_cast<C::RefineItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::CheckRefine):
                CheckRefine(static_cast<C::CheckRefine*>(p));
                break;
            case static_cast<short>(ClientPacketIds::ReplaceWedRing):
                ReplaceWedRing(static_cast<C::ReplaceWedRing*>(p));
                break;
            case static_cast<short>(ClientPacketIds::DepositTradeItem):
                DepositTradeItem(static_cast<C::DepositTradeItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::RetrieveTradeItem):
                RetrieveTradeItem(static_cast<C::RetrieveTradeItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::TakeBackItem):
                TakeBackItem(static_cast<C::TakeBackItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::MergeItem):
                MergeItem(static_cast<C::MergeItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::EquipItem):
                EquipItem(static_cast<C::EquipItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::RemoveItem):
                RemoveItem(static_cast<C::RemoveItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::RemoveSlotItem):
                RemoveSlotItem(static_cast<C::RemoveSlotItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::SplitItem):
                SplitItem(static_cast<C::SplitItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::UseItem):
                UseItem(static_cast<C::UseItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::DropItem):
                DropItem(static_cast<C::DropItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::DropGold):
                DropGold(static_cast<C::DropGold*>(p));
                break;
            case static_cast<short>(ClientPacketIds::PickUp):
                PickUp();
                break;
            case static_cast<short>(ClientPacketIds::Inspect):
                Inspect(static_cast<C::Inspect*>(p));
                break;
            case static_cast<short>(ClientPacketIds::ChangeAMode):
                ChangeAMode(static_cast<C::ChangeAMode*>(p));
                break;
            case static_cast<short>(ClientPacketIds::ChangePMode):
                ChangePMode(static_cast<C::ChangePMode*>(p));
                break;
            case static_cast<short>(ClientPacketIds::ChangeTrade):
                ChangeTrade(static_cast<C::ChangeTrade*>(p));
                break;
            case static_cast<short>(ClientPacketIds::Attack):
                Attack(static_cast<C::Attack*>(p));
                break;
            case static_cast<short>(ClientPacketIds::RangeAttack):
                RangeAttack(static_cast<C::RangeAttack*>(p));
                break;
            case static_cast<short>(ClientPacketIds::Harvest):
                Harvest(static_cast<C::Harvest*>(p));
                break;
            case static_cast<short>(ClientPacketIds::CallNPC):
                CallNPC(static_cast<C::CallNPC*>(p));
                break;
            case static_cast<short>(ClientPacketIds::BuyItem):
                BuyItem(static_cast<C::BuyItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::CraftItem):
                CraftItem(static_cast<C::CraftItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::SellItem):
                SellItem(static_cast<C::SellItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::RepairItem):
                RepairItem(static_cast<C::RepairItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::BuyItemBack):
                BuyItemBack(static_cast<C::BuyItemBack*>(p));
                break;
            case static_cast<short>(ClientPacketIds::SRepairItem):
                SRepairItem(static_cast<C::SRepairItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::MagicKey):
                MagicKey(static_cast<C::MagicKey*>(p));
                break;
            case static_cast<short>(ClientPacketIds::Magic):
                Magic(static_cast<C::Magic*>(p));
                break;
            case static_cast<short>(ClientPacketIds::SwitchGroup):
                SwitchGroup(static_cast<C::SwitchGroup*>(p));
                return;
            case static_cast<short>(ClientPacketIds::AddMember):
                AddMember(static_cast<C::AddMember*>(p));
                return;
            case static_cast<short>(ClientPacketIds::DellMember):
                DelMember(static_cast<C::DelMember*>(p));
                return;
            case static_cast<short>(ClientPacketIds::GroupInvite):
                GroupInvite(static_cast<C::GroupInvite*>(p));
                return;
            case static_cast<short>(ClientPacketIds::TownRevive):
                TownRevive();
                return;
            case static_cast<short>(ClientPacketIds::SpellToggle):
                SpellToggle(static_cast<C::SpellToggle*>(p));
                return;
            case static_cast<short>(ClientPacketIds::ConsignItem):
                ConsignItem(static_cast<C::ConsignItem*>(p));
                return;
            case static_cast<short>(ClientPacketIds::MarketSearch):
                MarketSearch(static_cast<C::MarketSearch*>(p));
                return;
            case static_cast<short>(ClientPacketIds::MarketRefresh):
                MarketRefresh();
                return;
            case static_cast<short>(ClientPacketIds::MarketPage):
                MarketPage(static_cast<C::MarketPage*>(p));
                return;
            case static_cast<short>(ClientPacketIds::MarketBuy):
                MarketBuy(static_cast<C::MarketBuy*>(p));
                return;
            case static_cast<short>(ClientPacketIds::MarketGetBack):
                MarketGetBack(static_cast<C::MarketGetBack*>(p));
                return;
            case static_cast<short>(ClientPacketIds::MarketSellNow):
                MarketSellNow(static_cast<C::MarketSellNow*>(p));
                return;
            case static_cast<short>(ClientPacketIds::RequestUserName):
                RequestUserName(static_cast<C::RequestUserName*>(p));
                return;
            case static_cast<short>(ClientPacketIds::RequestChatItem):
                RequestChatItem(static_cast<C::RequestChatItem*>(p));
                return;
            case static_cast<short>(ClientPacketIds::EditGuildMember):
                EditGuildMember(static_cast<C::EditGuildMember*>(p));
                return;
            case static_cast<short>(ClientPacketIds::EditGuildNotice):
                EditGuildNotice(static_cast<C::EditGuildNotice*>(p));
                return;
            case static_cast<short>(ClientPacketIds::GuildInvite):
                GuildInvite(static_cast<C::GuildInvite*>(p));
                return;
            case static_cast<short>(ClientPacketIds::RequestGuildInfo):
                RequestGuildInfo(static_cast<C::RequestGuildInfo*>(p));
                return;
            case static_cast<short>(ClientPacketIds::GuildNameReturn):
                GuildNameReturn(static_cast<C::GuildNameReturn*>(p));
                return;
            case static_cast<short>(ClientPacketIds::GuildStorageGoldChange):
                GuildStorageGoldChange(static_cast<C::GuildStorageGoldChange*>(p));
                return;
            case static_cast<short>(ClientPacketIds::GuildStorageItemChange):
                GuildStorageItemChange(static_cast<C::GuildStorageItemChange*>(p));
                return;
            case static_cast<short>(ClientPacketIds::GuildWarReturn):
                GuildWarReturn(static_cast<C::GuildWarReturn*>(p));
                return;
            case static_cast<short>(ClientPacketIds::MarriageRequest):
                MarriageRequest(static_cast<C::MarriageRequest*>(p));
                return;
            case static_cast<short>(ClientPacketIds::MarriageReply):
                MarriageReply(static_cast<C::MarriageReply*>(p));
                return;
            case static_cast<short>(ClientPacketIds::ChangeMarriage):
                ChangeMarriage(static_cast<C::ChangeMarriage*>(p));
                return;
            case static_cast<short>(ClientPacketIds::DivorceRequest):
                DivorceRequest(static_cast<C::DivorceRequest*>(p));
                return;
            case static_cast<short>(ClientPacketIds::DivorceReply):
                DivorceReply(static_cast<C::DivorceReply*>(p));
                return;
            case static_cast<short>(ClientPacketIds::AddMentor):
                AddMentor(static_cast<C::AddMentor*>(p));
                return;
            case static_cast<short>(ClientPacketIds::MentorReply):
                MentorReply(static_cast<C::MentorReply*>(p));
                return;
            case static_cast<short>(ClientPacketIds::AllowMentor):
                AllowMentor(static_cast<C::AllowMentor*>(p));
                return;
            case static_cast<short>(ClientPacketIds::CancelMentor):
                CancelMentor(static_cast<C::CancelMentor*>(p));
                return;
            case static_cast<short>(ClientPacketIds::TradeRequest):
                TradeRequest(static_cast<C::TradeRequest*>(p));
                return;
            case static_cast<short>(ClientPacketIds::TradeGold):
                TradeGold(static_cast<C::TradeGold*>(p));
                return;
            case static_cast<short>(ClientPacketIds::TradeReply):
                TradeReply(static_cast<C::TradeReply*>(p));
                return;
            case static_cast<short>(ClientPacketIds::TradeConfirm):
                TradeConfirm(static_cast<C::TradeConfirm*>(p));
                return;
            case static_cast<short>(ClientPacketIds::TradeCancel):
                TradeCancel(static_cast<C::TradeCancel*>(p));
                return;
            case static_cast<short>(ClientPacketIds::EquipSlotItem):
                EquipSlotItem(static_cast<C::EquipSlotItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::FishingCast):
                FishingCast(static_cast<C::FishingCast*>(p));
                break;
            case static_cast<short>(ClientPacketIds::FishingChangeAutocast):
                FishingChangeAutocast(static_cast<C::FishingChangeAutocast*>(p));
                break;
            case static_cast<short>(ClientPacketIds::AcceptQuest):
                AcceptQuest(static_cast<C::AcceptQuest*>(p));
                break;
            case static_cast<short>(ClientPacketIds::FinishQuest):
                FinishQuest(static_cast<C::FinishQuest*>(p));
                break;
            case static_cast<short>(ClientPacketIds::AbandonQuest):
                AbandonQuest(static_cast<C::AbandonQuest*>(p));
                break;
            case static_cast<short>(ClientPacketIds::ShareQuest):
                ShareQuest(static_cast<C::ShareQuest*>(p));
                break;
            case static_cast<short>(ClientPacketIds::AcceptReincarnation):
                AcceptReincarnation();
                break;
            case static_cast<short>(ClientPacketIds::CancelReincarnation):
                 CancelReincarnation();
                break;
            case static_cast<short>(ClientPacketIds::CombineItem):
                CombineItem(static_cast<C::CombineItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::AwakeningNeedMaterials):
                AwakeningNeedMaterials(static_cast<C::AwakeningNeedMaterials*>(p));
                break;
            case static_cast<short>(ClientPacketIds::AwakeningLockedItem):
                S::AwakeningLockedItem *tempVar = new S::AwakeningLockedItem();
                tempVar->UniqueID = (static_cast<C::AwakeningLockedItem*>(p))->UniqueID;
                tempVar->Locked = (static_cast<C::AwakeningLockedItem*>(p))->Locked;
                Enqueue(tempVar);
                break;
            case static_cast<short>(ClientPacketIds::Awakening):
                Awakening(static_cast<C::Awakening*>(p));
                break;
            case static_cast<short>(ClientPacketIds::DisassembleItem):
                DisassembleItem(static_cast<C::DisassembleItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::DowngradeAwakening):
                DowngradeAwakening(static_cast<C::DowngradeAwakening*>(p));
                break;
            case static_cast<short>(ClientPacketIds::ResetAddedItem):
                ResetAddedItem(static_cast<C::ResetAddedItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::SendMail):
                SendMail(static_cast<C::SendMail*>(p));
                break;
            case static_cast<short>(ClientPacketIds::ReadMail):
                ReadMail(static_cast<C::ReadMail*>(p));
                break;
            case static_cast<short>(ClientPacketIds::CollectParcel):
                CollectParcel(static_cast<C::CollectParcel*>(p));
                break;
            case static_cast<short>(ClientPacketIds::DeleteMail):
                DeleteMail(static_cast<C::DeleteMail*>(p));
                break;
            case static_cast<short>(ClientPacketIds::LockMail):
                LockMail(static_cast<C::LockMail*>(p));
                break;
            case static_cast<short>(ClientPacketIds::MailLockedItem):
                S::MailLockedItem *tempVar2 = new S::MailLockedItem();
                tempVar2->UniqueID = (static_cast<C::MailLockedItem*>(p))->UniqueID;
                tempVar2->Locked = (static_cast<C::MailLockedItem*>(p))->Locked;
                Enqueue(tempVar2);
                break;
            case static_cast<short>(ClientPacketIds::MailCost):
                MailCost(static_cast<C::MailCost*>(p));
                break;
            case static_cast<short>(ClientPacketIds::RequestIntelligentCreatureUpdates): //IntelligentCreature
                RequestIntelligentCreatureUpdates(static_cast<C::RequestIntelligentCreatureUpdates*>(p));
                break;
            case static_cast<short>(ClientPacketIds::UpdateIntelligentCreature): //IntelligentCreature
                UpdateIntelligentCreature(static_cast<C::UpdateIntelligentCreature*>(p));
                break;
            case static_cast<short>(ClientPacketIds::IntelligentCreaturePickup): //IntelligentCreature
                IntelligentCreaturePickup(static_cast<C::IntelligentCreaturePickup*>(p));
                break;
            case static_cast<short>(ClientPacketIds::AddFriend):
                AddFriend(static_cast<C::AddFriend*>(p));
                break;
            case static_cast<short>(ClientPacketIds::RemoveFriend):
                RemoveFriend(static_cast<C::RemoveFriend*>(p));
                break;
            case static_cast<short>(ClientPacketIds::RefreshFriends):
            {
                    if (Stage != GameStage::Game)
                    {
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
                        return;
                    }
                    Player->GetFriends();
                    break;
            }
            case static_cast<short>(ClientPacketIds::AddMemo):
                AddMemo(static_cast<C::AddMemo*>(p));
                break;
            case static_cast<short>(ClientPacketIds::GuildBuffUpdate):
                GuildBuffUpdate(static_cast<C::GuildBuffUpdate*>(p));
                break;
            case static_cast<short>(ClientPacketIds::GameshopBuy):
                GameshopBuy(static_cast<C::GameshopBuy*>(p));

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
                return;
            case static_cast<short>(ClientPacketIds::NPCConfirmInput):
                NPCConfirmInput(static_cast<C::NPCConfirmInput*>(p));
                break;
            case static_cast<short>(ClientPacketIds::ReportIssue):
                ReportIssue(static_cast<C::ReportIssue*>(p));
                break;
            case static_cast<short>(ClientPacketIds::GetRanking):
                GetRanking(static_cast<C::GetRanking*>(p));
                break;
            case static_cast<short>(ClientPacketIds::Opendoor):
                Opendoor(static_cast<C::Opendoor*>(p));
                break;
            case static_cast<short>(ClientPacketIds::GetRentedItems):
                GetRentedItems();
                break;
            case static_cast<short>(ClientPacketIds::ItemRentalRequest):
                ItemRentalRequest();
                break;
            case static_cast<short>(ClientPacketIds::ItemRentalFee):
                ItemRentalFee(static_cast<C::ItemRentalFee*>(p));
                break;
            case static_cast<short>(ClientPacketIds::ItemRentalPeriod):
                ItemRentalPeriod(static_cast<C::ItemRentalPeriod*>(p));
                break;
            case static_cast<short>(ClientPacketIds::DepositRentalItem):
                DepositRentalItem(static_cast<C::DepositRentalItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::RetrieveRentalItem):
                RetrieveRentalItem(static_cast<C::RetrieveRentalItem*>(p));
                break;
            case static_cast<short>(ClientPacketIds::CancelItemRental):
                CancelItemRental();
                break;
            case static_cast<short>(ClientPacketIds::ItemRentalLockFee):
                ItemRentalLockFee();
                break;
            case static_cast<short>(ClientPacketIds::ItemRentalLockItem):
                ItemRentalLockItem();
                break;
            case static_cast<short>(ClientPacketIds::ConfirmItemRental):
                ConfirmItemRental();
                break;
            default:
                getMessageQueue()->Enqueue(StringHelper::formatSimple("Invalid packet received. Index : {0}", p->getIndex()));
                break;
        }
    }

    void MirConnection::SoftDisconnect(unsigned char reason)
    {
        Stage = GameStage::Disconnected;
        TimeDisconnected = getEnvir()->getTime();

        {
            std::scoped_lock<std::mutex> lock(Envir::AccountLock);
            if (Player != nullptr)
            {
                Player->StopGame(reason);
            }

            if (Account != nullptr && Account->Connection == this)
            {
                Account->Connection = nullptr;
            }
        }

        Account = nullptr;
    }

    void MirConnection::Disconnect(unsigned char reason)
    {
        if (!Connected)
        {
            return;
        }

        Connected = false;
        Stage = GameStage::Disconnected;
        TimeDisconnected = getEnvir()->getTime();

        {
            std::scoped_lock<std::mutex> lock(getEnvir()->Connections);
            getEnvir()->Connections.Remove(this);
        }

        {
            std::scoped_lock<std::mutex> lock(Envir::AccountLock);
            if (Player != nullptr)
            {
                Player->StopGame(reason);
            }

            if (Account != nullptr && Account->Connection == this)
            {
                Account->Connection = nullptr;
            }

        }

        Account = nullptr;

        _sendList = nullptr;
        _receiveList = nullptr;
        _retryList = std::deque<Packet*>();
        _rawData = std::vector<unsigned char>();

        if (_client != nullptr)
        {
            _client->Client->Dispose();
        }
        _client = nullptr;
    }

    void MirConnection::SendDisconnect(unsigned char reason)
    {
        if (!Connected)
        {
            setDisconnecting(true);
            SoftDisconnect(reason);
            return;
        }

        setDisconnecting(true);

        std::vector<unsigned char> data;

        S::Disconnect *tempVar = new S::Disconnect();
        tempVar->Reason = reason;
        data.AddRange(tempVar->GetPacketBytes());

        BeginSend(data);
        SoftDisconnect(reason);

        delete tempVar;
    }

    void MirConnection::ClientVersion(C::ClientVersion *p)
    {
        if (Stage != GameStage::None)
        {
            return;
        }

        if (Settings::CheckVersion)
        {
            bool match = false;

            for (auto hash : Settings::VersionHashes)
            {
                if (Functions::CompareBytes(hash, p->VersionHash))
                {
                    match = true;
                    break;
                }
            }

            if (!match)
            {
                setDisconnecting(true);

                std::vector<unsigned char> data;

                S::ClientVersion *tempVar = new S::ClientVersion();
                tempVar->Result = 0;
                data.AddRange(tempVar->GetPacketBytes());

                BeginSend(data);
                SoftDisconnect(10);
                getMessageQueue()->Enqueue(std::to_string(SessionID) + ", Disconnnected - Wrong Client Version.");

                delete tempVar;
                return;
            }
        }

        getMessageQueue()->Enqueue(std::to_string(SessionID) + ", " + IPAddress + ", Client version matched.");
        S::ClientVersion *tempVar2 = new S::ClientVersion();
        tempVar2->Result = 1;
        Enqueue(tempVar2);

        Stage = GameStage::Login;

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
    }

    void MirConnection::ClientKeepAlive(C::KeepAlive *p)
    {
        S::KeepAlive *tempVar = new S::KeepAlive();
        tempVar->Time = p->Time;
        Enqueue(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void MirConnection::NewAccount(C::NewAccount *p)
    {
        if (Stage != GameStage::Login)
        {
            return;
        }

        getMessageQueue()->Enqueue(std::to_string(SessionID) + ", " + IPAddress + ", New account being created.");
        getEnvir()->NewAccount(p, this);
    }

    void MirConnection::ChangePassword(C::ChangePassword *p)
    {
        if (Stage != GameStage::Login)
        {
            return;
        }

        getMessageQueue()->Enqueue(std::to_string(SessionID) + ", " + IPAddress + ", Password being changed.");
        getEnvir()->ChangePassword(p, this);
    }

    void MirConnection::Login(C::Login *p)
    {
        if (Stage != GameStage::Login)
        {
            return;
        }

        getMessageQueue()->Enqueue(std::to_string(SessionID) + ", " + IPAddress + ", User logging in.");
        getEnvir()->Login(p, this);
    }

    void MirConnection::NewCharacter(C::NewCharacter *p)
    {
        if (Stage != GameStage::Select)
        {
            return;
        }

        getEnvir()->NewCharacter(p, this, Account->AdminAccount);
    }

    void MirConnection::DeleteCharacter(C::DeleteCharacter *p)
    {
        if (Stage != GameStage::Select)
        {
            return;
        }

        if (!Settings::AllowDeleteCharacter)
        {
            S::DeleteCharacter *tempVar = new S::DeleteCharacter();
            tempVar->Result = 0;
            Enqueue(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            return;
        }

        CharacterInfo *temp = nullptr;


        for (int i = 0; i < Account->Characters.size(); i++)
        {
            if (Account->Characters[i]->Index != p->CharacterIndex)
            {
                continue;
            }

            temp = Account->Characters[i];
            break;
        }

        if (temp == nullptr)
        {
            S::DeleteCharacter *tempVar2 = new S::DeleteCharacter();
            tempVar2->Result = 1;
            Enqueue(tempVar2);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        temp->Deleted = true;
        temp->DeleteDate = getEnvir()->getNow();
        getEnvir()->RemoveRank(temp);
        S::DeleteCharacterSuccess *tempVar3 = new S::DeleteCharacterSuccess();
        tempVar3->CharacterIndex = temp->Index;
        Enqueue(tempVar3);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar3' statement was not added since tempVar3 was passed to a method or constructor. Handle memory management manually.
    }

    void MirConnection::StartGame(C::StartGame *p)
    {
        if (Stage != GameStage::Select)
        {
            return;
        }

        if (!Settings::AllowStartGame && (Account == nullptr || (Account != nullptr && !Account->AdminAccount)))
        {
            S::StartGame *tempVar = new S::StartGame();
            tempVar->Result = 0;
            Enqueue(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (Account == nullptr)
        {
            S::StartGame *tempVar2 = new S::StartGame();
            tempVar2->Result = 1;
            Enqueue(tempVar2);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
            return;
        }


        CharacterInfo *info = nullptr;

        for (int i = 0; i < Account->Characters.size(); i++)
        {
            if (Account->Characters[i]->Index != p->CharacterIndex)
            {
                continue;
            }

            info = Account->Characters[i];
            break;
        }
        if (info == nullptr)
        {
            S::StartGame *tempVar3 = new S::StartGame();
            tempVar3->Result = 2;
            Enqueue(tempVar3);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar3' statement was not added since tempVar3 was passed to a method or constructor. Handle memory management manually.
            return;
        }

        if (info->Banned)
        {
            if (info->ExpiryDate > DateTime::Now)
            {
                S::StartGameBanned *tempVar4 = new S::StartGameBanned();
                tempVar4->Reason = info->BanReason;
                tempVar4->ExpiryDate = info->ExpiryDate;
                Enqueue(tempVar4);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar4' statement was not added since tempVar4 was passed to a method or constructor. Handle memory management manually.
                return;
            }
            info->Banned = false;
        }
        info->BanReason = "";
        info->ExpiryDate = DateTime::MinValue;

        long long delay = static_cast<long long>((getEnvir()->getNow() - info->LastLogoutDate).TotalMilliseconds);


        //if (delay < Settings.RelogDelay)
        //{
        //    Enqueue(new S.StartGameDelay { Milliseconds = Settings.RelogDelay - delay });
        //    return;
        //}

        Player = new PlayerObject(info, this);
        Player->StartGame();
    }

    void MirConnection::LogOut()
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        if (getEnvir()->getTime() < Player->LogTime)
        {
            S::LogOutFailed tempVar();
            Enqueue(&tempVar);
            return;
        }

        Player->StopGame(23);

        Stage = GameStage::Select;
        Player = nullptr;

        S::LogOutSuccess *tempVar2 = new S::LogOutSuccess();
        tempVar2->Characters = Account->GetSelectInfo();
        Enqueue(tempVar2);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar2' statement was not added since tempVar2 was passed to a method or constructor. Handle memory management manually.
    }

    void MirConnection::Turn(C::Turn *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        if (Player->ActionTime > getEnvir()->getTime())
        {
            _retryList.push_back(p);
        }
        else
        {
            Player->Turn(p->Direction);
        }
    }

    void MirConnection::Walk(C::Walk *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        if (Player->ActionTime > getEnvir()->getTime())
        {
            _retryList.push_back(p);
        }
        else
        {
            Player->Walk(p->Direction);
        }
    }

    void MirConnection::Run(C::Run *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        if (Player->ActionTime > getEnvir()->getTime())
        {
            _retryList.push_back(p);
        }
        else
        {
            Player->Run(p->Direction);
        }
    }

    void MirConnection::Chat(C::Chat *p)
    {
        if (p->Message.length() > Globals::MaxChatLength)
        {
            SendDisconnect(2);
            return;
        }

        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->Chat(p->Message, p->LinkedItems);
    }

    void MirConnection::MoveItem(C::MoveItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->MoveItem(p->Grid, p->From, p->To);
    }

    void MirConnection::StoreItem(C::StoreItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->StoreItem(p->From, p->To);
    }

    void MirConnection::DepositRefineItem(C::DepositRefineItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->DepositRefineItem(p->From, p->To);
    }

    void MirConnection::RetrieveRefineItem(C::RetrieveRefineItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->RetrieveRefineItem(p->From, p->To);
    }

    void MirConnection::RefineCancel(C::RefineCancel *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->RefineCancel();
    }

    void MirConnection::RefineItem(C::RefineItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->RefineItem(p->UniqueID);
    }

    void MirConnection::CheckRefine(C::CheckRefine *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->CheckRefine(p->UniqueID);
    }

    void MirConnection::ReplaceWedRing(C::ReplaceWedRing *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->ReplaceWeddingRing(p->UniqueID);
    }

    void MirConnection::DepositTradeItem(C::DepositTradeItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->DepositTradeItem(p->From, p->To);
    }

    void MirConnection::RetrieveTradeItem(C::RetrieveTradeItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->RetrieveTradeItem(p->From, p->To);
    }

    void MirConnection::TakeBackItem(C::TakeBackItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->TakeBackItem(p->From, p->To);
    }

    void MirConnection::MergeItem(C::MergeItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->MergeItem(p->GridFrom, p->GridTo, p->IDFrom, p->IDTo);
    }

    void MirConnection::EquipItem(C::EquipItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->EquipItem(p->Grid, p->UniqueID, p->To);
    }

    void MirConnection::RemoveItem(C::RemoveItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->RemoveItem(p->Grid, p->UniqueID, p->To);
    }

    void MirConnection::RemoveSlotItem(C::RemoveSlotItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->RemoveSlotItem(p->Grid, p->UniqueID, p->To, p->GridTo, p->FromUniqueID);
    }

    void MirConnection::SplitItem(C::SplitItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->SplitItem(p->Grid, p->UniqueID, p->Count);
    }

    void MirConnection::UseItem(C::UseItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->UseItem(p->UniqueID);
    }

    void MirConnection::DropItem(C::DropItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->DropItem(p->UniqueID, p->Count);
    }

    void MirConnection::DropGold(C::DropGold *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->DropGold(p->Amount);
    }

    void MirConnection::PickUp()
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->PickUp();
    }

    void MirConnection::Inspect(C::Inspect *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        if (p->Ranking)
        {
            Player->Inspect(static_cast<int>(p->ObjectID));
        }
        else
        {
            Player->Inspect(p->ObjectID);
        }
    }

    void MirConnection::ChangeAMode(C::ChangeAMode *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->setAMode(p->Mode);

        S::ChangeAMode *tempVar = new S::ChangeAMode();
        tempVar->Mode = Player->getAMode();
        Enqueue(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void MirConnection::ChangePMode(C::ChangePMode *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->setPMode(p->Mode);

        S::ChangePMode *tempVar = new S::ChangePMode();
        tempVar->Mode = Player->getPMode();
        Enqueue(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void MirConnection::ChangeTrade(C::ChangeTrade *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->setAllowTrade(p->AllowTrade);
    }

    void MirConnection::Attack(C::Attack *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        if (!Player->Dead && (Player->ActionTime > getEnvir()->getTime() || Player->AttackTime > getEnvir()->getTime()))
        {
            _retryList.push_back(p);
        }
        else
        {
            Player->Attack(p->Direction, p->Spell);
        }
    }

    void MirConnection::RangeAttack(C::RangeAttack *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        if (!Player->Dead && (Player->ActionTime > getEnvir()->getTime() || Player->AttackTime > getEnvir()->getTime()))
        {
            _retryList.push_back(p);
        }
        else
        {
            Player->RangeAttack(p->Direction, p->TargetLocation, p->TargetID);
        }
    }

    void MirConnection::Harvest(C::Harvest *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        if (!Player->Dead && Player->ActionTime > getEnvir()->getTime())
        {
            _retryList.push_back(p);
        }
        else
        {
            Player->Harvest(p->Direction);
        }
    }

    void MirConnection::CallNPC(C::CallNPC *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        if (p->Key.length() > 30) //No NPC Key should be that long.
        {
            SendDisconnect(2);
            return;
        }

        if (p->ObjectID == Player->getDefaultNPC()->LoadedObjectID && Player->NPCObjectID == Player->getDefaultNPC()->LoadedObjectID)
        {
            Player->CallDefaultNPC(p->Key);
            return;
        }

        if (p->ObjectID == std::numeric_limits<unsigned int>::max())
        {
            Player->CallDefaultNPC(DefaultNPCType::Client, {std::any()});
            return;
        }

        Player->CallNPC(p->ObjectID, p->Key);
    }

    void MirConnection::BuyItem(C::BuyItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->BuyItem(p->ItemIndex, p->Count, p->Type);
    }

    void MirConnection::CraftItem(C::CraftItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->CraftItem(p->UniqueID, p->Count, p->Slots);
    }

    void MirConnection::SellItem(C::SellItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->SellItem(p->UniqueID, p->Count);
    }

    void MirConnection::RepairItem(C::RepairItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->RepairItem(p->UniqueID);
    }

    void MirConnection::BuyItemBack(C::BuyItemBack *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

       // Player.BuyItemBack(p.UniqueID, p.Count);
    }

    void MirConnection::SRepairItem(C::SRepairItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->RepairItem(p->UniqueID, true);
    }

    void MirConnection::MagicKey(C::MagicKey *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        for (int i = 0; i < Player->Info->Magics.size(); i++)
        {
            UserMagic *magic = Player->Info->Magics[i];
            if (magic->Spell != p->Spell)
            {
                if (magic->Key == p->Key)
                {
                    magic->Key = 0;
                }
                continue;
            }

            magic->Key = p->Key;
        }
    }

    void MirConnection::Magic(C::Magic *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        if (!Player->Dead && (Player->ActionTime > getEnvir()->getTime() || Player->SpellTime > getEnvir()->getTime()))
        {
            _retryList.push_back(p);
        }
        else
        {
            Player->Magic(p->Spell, p->Direction, p->TargetID, p->Location);
        }
    }

    void MirConnection::SwitchGroup(C::SwitchGroup *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->SwitchGroup(p->AllowGroup);
    }

    void MirConnection::AddMember(C::AddMember *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->AddMember(p->Name);
    }

    void MirConnection::DelMember(C::DelMember *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->DelMember(p->Name);
    }

    void MirConnection::GroupInvite(C::GroupInvite *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->GroupInvite(p->AcceptInvite);
    }

    void MirConnection::TownRevive()
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->TownRevive();
    }

    void MirConnection::SpellToggle(C::SpellToggle *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->SpellToggle(p->Spell, p->CanUse);
    }

    void MirConnection::ConsignItem(C::ConsignItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->ConsignItem(p->UniqueID, p->Price, p->Type);
    }

    void MirConnection::MarketSearch(C::MarketSearch *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->UserMatch = p->Usermode;
        Player->MinShapes = p->MinShape;
        Player->MaxShapes = p->MaxShape;
        Player->MarketPanelType = p->MarketType;

        Player->MarketSearch(p->Match, p->Type);
    }

    void MirConnection::MarketRefresh()
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->MarketSearch("", Player->MatchType);
    }

    void MirConnection::MarketPage(C::MarketPage *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->MarketPage(p->Page);
    }

    void MirConnection::MarketBuy(C::MarketBuy *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->MarketBuy(p->AuctionID, p->BidPrice);
    }

    void MirConnection::MarketSellNow(C::MarketSellNow *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->MarketSellNow(p->AuctionID);
    }

    void MirConnection::MarketGetBack(C::MarketGetBack *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->MarketGetBack(p->AuctionID);
    }

    void MirConnection::RequestUserName(C::RequestUserName *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->RequestUserName(p->UserID);
    }

    void MirConnection::RequestChatItem(C::RequestChatItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->RequestChatItem(p->ChatItemID);
    }

    void MirConnection::EditGuildMember(C::EditGuildMember *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }
        Player->EditGuildMember(p->Name,p->RankName,p->RankIndex,p->ChangeType);
    }

    void MirConnection::EditGuildNotice(C::EditGuildNotice *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }
        Player->EditGuildNotice(p->notice);
    }

    void MirConnection::GuildInvite(C::GuildInvite *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->GuildInvite(p->AcceptInvite);
    }

    void MirConnection::RequestGuildInfo(C::RequestGuildInfo *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }
        Player->RequestGuildInfo(p->Type);
    }

    void MirConnection::GuildNameReturn(C::GuildNameReturn *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }
        Player->GuildNameReturn(p->Name);
    }

    void MirConnection::GuildStorageGoldChange(C::GuildStorageGoldChange *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }
        Player->GuildStorageGoldChange(p->Type, p->Amount);
    }

    void MirConnection::GuildStorageItemChange(C::GuildStorageItemChange *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }
        Player->GuildStorageItemChange(p->Type, p->From, p->To);
    }

    void MirConnection::GuildWarReturn(C::GuildWarReturn *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }
        Player->GuildWarReturn(p->Name);
    }

    void MirConnection::MarriageRequest(C::MarriageRequest *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->MarriageRequest();
    }

    void MirConnection::MarriageReply(C::MarriageReply *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->MarriageReply(p->AcceptInvite);
    }

    void MirConnection::ChangeMarriage(C::ChangeMarriage *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        if (Player->Info->Married == 0)
        {
            Player->AllowMarriage = !Player->AllowMarriage;
            if (Player->AllowMarriage)
            {
                Player->ReceiveChat("You're now allowing marriage requests.", ChatType::Hint);
            }
            else
            {
                Player->ReceiveChat("You're now blocking marriage requests.", ChatType::Hint);
            }
        }
        else
        {
            Player->AllowLoverRecall = !Player->AllowLoverRecall;
            if (Player->AllowLoverRecall)
            {
                Player->ReceiveChat("You're now allowing recall from lover.", ChatType::Hint);
            }
            else
            {
                Player->ReceiveChat("You're now blocking recall from lover.", ChatType::Hint);
            }
        }
    }

    void MirConnection::DivorceRequest(C::DivorceRequest *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->DivorceRequest();
    }

    void MirConnection::DivorceReply(C::DivorceReply *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->DivorceReply(p->AcceptInvite);
    }

    void MirConnection::AddMentor(C::AddMentor *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->AddMentor(p->Name);
    }

    void MirConnection::MentorReply(C::MentorReply *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->MentorReply(p->AcceptInvite);
    }

    void MirConnection::AllowMentor(C::AllowMentor *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

            Player->AllowMentor = !Player->AllowMentor;
            if (Player->AllowMentor)
            {
                Player->ReceiveChat(GameLanguage::AllowingMentorRequests, ChatType::Hint);
            }
            else
            {
                Player->ReceiveChat(GameLanguage::BlockingMentorRequests, ChatType::Hint);
            }
    }

    void MirConnection::CancelMentor(C::CancelMentor *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->MentorBreak(true);
    }

    void MirConnection::TradeRequest(C::TradeRequest *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->TradeRequest();
    }

    void MirConnection::TradeGold(C::TradeGold *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->TradeGold(p->Amount);
    }

    void MirConnection::TradeReply(C::TradeReply *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->TradeReply(p->AcceptInvite);
    }

    void MirConnection::TradeConfirm(C::TradeConfirm *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->TradeConfirm(p->Locked);
    }

    void MirConnection::TradeCancel(C::TradeCancel *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->TradeCancel();
    }

    void MirConnection::EquipSlotItem(C::EquipSlotItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->EquipSlotItem(p->Grid, p->UniqueID, p->To, p->GridTo, p->ToUniqueID);
    }

    void MirConnection::FishingCast(C::FishingCast *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->FishingCast(p->CastOut, true);
    }

    void MirConnection::FishingChangeAutocast(C::FishingChangeAutocast *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->FishingChangeAutocast(p->AutoCast);
    }

    void MirConnection::AcceptQuest(C::AcceptQuest *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->AcceptQuest(p->QuestIndex); //p.NPCIndex,
    }

    void MirConnection::FinishQuest(C::FinishQuest *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->FinishQuest(p->QuestIndex, p->SelectedItemIndex);
    }

    void MirConnection::AbandonQuest(C::AbandonQuest *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->AbandonQuest(p->QuestIndex);
    }

    void MirConnection::ShareQuest(C::ShareQuest *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->ShareQuest(p->QuestIndex);
    }

    void MirConnection::AcceptReincarnation()
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        if (Player->ReincarnationHost != nullptr && Player->ReincarnationHost->ReincarnationReady)
        {
            Player->Revive(Player->Stats[Stat::HP] / 2, true);
            Player->ReincarnationHost = nullptr;
            return;
        }

        Player->ReceiveChat("Reincarnation failed", ChatType::System);
    }

    void MirConnection::CancelReincarnation()
    {
        if (Stage != GameStage::Game)
        {
            return;
        }
        Player->ReincarnationExpireTime = getEnvir()->getTime();

    }

    void MirConnection::CombineItem(C::CombineItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->CombineItem(p->IDFrom, p->IDTo);
    }

    void MirConnection::Awakening(C::Awakening *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->Awakening(p->UniqueID, p->Type);
    }

    void MirConnection::AwakeningNeedMaterials(C::AwakeningNeedMaterials *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->AwakeningNeedMaterials(p->UniqueID, p->Type);
    }

    void MirConnection::DisassembleItem(C::DisassembleItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->DisassembleItem(p->UniqueID);
    }

    void MirConnection::DowngradeAwakening(C::DowngradeAwakening *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->DowngradeAwakening(p->UniqueID);
    }

    void MirConnection::ResetAddedItem(C::ResetAddedItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->ResetAddedItem(p->UniqueID);
    }

    void MirConnection::SendMail(C::SendMail *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        if (p->Gold > 0 || p->ItemsIdx.size() > 0)
        {
            Player->SendMail(p->Name, p->Message, p->Gold, p->ItemsIdx, p->Stamped);
        }
        else
        {
            Player->SendMail(p->Name, p->Message);
        }
    }

    void MirConnection::ReadMail(C::ReadMail *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->ReadMail(p->MailID);
    }

    void MirConnection::CollectParcel(C::CollectParcel *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->CollectMail(p->MailID);
    }

    void MirConnection::DeleteMail(C::DeleteMail *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->DeleteMail(p->MailID);
    }

    void MirConnection::LockMail(C::LockMail *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->LockMail(p->MailID, p->Lock);
    }

    void MirConnection::MailCost(C::MailCost *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        unsigned int cost = Player->GetMailCost(p->ItemsIdx, p->Gold, p->Stamped);

        S::MailCost *tempVar = new S::MailCost();
        tempVar->Cost = cost;
        Enqueue(tempVar);

//C# TO C++ CONVERTER TODO TASK: A 'delete tempVar' statement was not added since tempVar was passed to a method or constructor. Handle memory management manually.
    }

    void MirConnection::RequestIntelligentCreatureUpdates(C::RequestIntelligentCreatureUpdates *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->SendIntelligentCreatureUpdates = p->Update;
    }

    void MirConnection::UpdateIntelligentCreature(C::UpdateIntelligentCreature *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        ClientIntelligentCreature *petUpdate = p->Creature;
        if (petUpdate == nullptr)
        {
            return;
        }

        if (p->ReleaseMe)
        {
            Player->ReleaseIntelligentCreature(petUpdate->PetType);
            return;
        }
        else if (p->SummonMe)
        {
            Player->SummonIntelligentCreature(petUpdate->PetType);
            return;
        }
        else if (p->UnSummonMe)
        {
            Player->UnSummonIntelligentCreature(petUpdate->PetType);
            return;
        }
        else
        {
            //Update the creature info
            for (int i = 0; i < Player->Info->IntelligentCreatures.size(); i++)
            {
                if (Player->SummonedCreatureType == petUpdate->PetType && Player->Info->IntelligentCreatures[i]->PetType == petUpdate->PetType)
                {
                    if (petUpdate->CustomName.length() <= 12)
                    {
                        Player->Info->IntelligentCreatures[i]->CustomName = petUpdate->CustomName;
                    }
                    Player->Info->IntelligentCreatures[i]->SlotIndex = petUpdate->SlotIndex;
                    Player->Info->IntelligentCreatures[i]->Filter = petUpdate->Filter;
                    Player->Info->IntelligentCreatures[i]->petMode = petUpdate->petMode;
                }
                else
                {
                    continue;
                }
            }

            if (Player->CreatureSummoned)
            {
                if (Player->SummonedCreatureType == petUpdate->PetType)
                {
                    Player->UpdateSummonedCreature(petUpdate->PetType);
                }
            }
        }
    }

    void MirConnection::IntelligentCreaturePickup(C::IntelligentCreaturePickup *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->IntelligentCreaturePickup(p->MouseMode, p->Location);
    }

    void MirConnection::AddFriend(C::AddFriend *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->AddFriend(p->Name, p->Blocked);
    }

    void MirConnection::RemoveFriend(C::RemoveFriend *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->RemoveFriend(p->CharacterIndex);
    }

    void MirConnection::AddMemo(C::AddMemo *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->AddMemo(p->CharacterIndex, p->Memo);
    }

    void MirConnection::GuildBuffUpdate(C::GuildBuffUpdate *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }
        Player->GuildBuffUpdate(p->Action,p->Id);
    }

    void MirConnection::GameshopBuy(C::GameshopBuy *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }
        Player->GameshopBuy(p->GIndex, p->Quantity);
    }

    void MirConnection::NPCConfirmInput(C::NPCConfirmInput *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->NPCInputStr = p->Value;

        Player->CallNPC(Player->NPCObjectID, p->PageName);
    }

    void MirConnection::ReportIssue(C::ReportIssue *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        return;

        // Image.Add(p.Image);

        // if (p.ImageChunk >= p.ImageSize)
        // {
        //     System.Drawing.Image image = Functions.ByteArrayToImage(Functions.CombineArray(Image));
        //     image.Save("Reported-" + Player.Name + "-" + DateTime.Now.ToString("yyMMddHHmmss") + ".jpg");
        //     Image.Clear();
        // }
    }

    void MirConnection::GetRanking(C::GetRanking *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }
        Player->GetRanking(p->RankIndex);
    }

    void MirConnection::Opendoor(C::Opendoor *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }
        Player->Opendoor(p->DoorIndex);
    }

    void MirConnection::GetRentedItems()
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->GetRentedItems();
    }

    void MirConnection::ItemRentalRequest()
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->ItemRentalRequest();
    }

    void MirConnection::ItemRentalFee(C::ItemRentalFee *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->SetItemRentalFee(p->Amount);
    }

    void MirConnection::ItemRentalPeriod(C::ItemRentalPeriod *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->SetItemRentalPeriodLength(p->Days);
    }

    void MirConnection::DepositRentalItem(C::DepositRentalItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->DepositRentalItem(p->From, p->To);
    }

    void MirConnection::RetrieveRentalItem(C::RetrieveRentalItem *p)
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->RetrieveRentalItem(p->From, p->To);
    }

    void MirConnection::CancelItemRental()
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->CancelItemRental();
    }

    void MirConnection::ItemRentalLockFee()
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->ItemRentalLockFee();
    }

    void MirConnection::ItemRentalLockItem()
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->ItemRentalLockItem();
    }

    void MirConnection::ConfirmItemRental()
    {
        if (Stage != GameStage::Game)
        {
            return;
        }

        Player->ConfirmItemRental();
    }
}
